/**************************************************************************************************
**
**  文件名称:  osl_dbg_man.c
**  版权所有:  CopyRight @ Xiamen Yaxon NetWork CO.LTD. 2018
**  文件描述:  系统调试打印模块
**  ===============================================================================================
**  创建信息:  | 2018-6-9 | LEON | 创建本模块
**  ===============================================================================================
**  修改信息:  单击此处添加....
**************************************************************************************************/
#include "osl_include.h"
#include "osl_dbg_man.h"

#if EN_DEBUG > 0

/*************************************************************************************************/
/*                                     重定义系统打印函数                                        */
/*************************************************************************************************/
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE  int  __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE  int  fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
    Debug_PrintByte((INT8U)ch);                                      /* Write a character to USART */
    return ch;
}

/**************************************************************************************************
**  函数名称:  GetGPIOPin
**  功能描述:  调试管脚映射
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static INT8U GetGPIOPin(INT16U pnum)
{
    INT8U pinsource;
    
    for (pinsource = 0; pinsource < 0x0F; pinsource++) {
        
        if (pnum & 0x0001) {
            break;
        }
        pnum >>= 1;
    }
    
    return pinsource;
}

/**************************************************************************************************
**  函数名称:  UART_IOCONFIG
**  功能描述:  USARTX的IO口配置
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void UART_IOCONFIG(USART_INDEX_E index)
{
    GPIO_InitTypeDef ICB;
    
    ICB.GPIO_Mode  = GPIO_Mode_AF;
    ICB.GPIO_Speed = GPIO_Speed_100MHz;
    ICB.GPIO_OType = GPIO_OType_PP;
    ICB.GPIO_PuPd  = GPIO_PuPd_UP;
    
    switch (index)                                                              /* 配置串口管脚并锁定配置 */
    {
        case USART_NO1:
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);              /* Enable USART clock */
            GPIO_PinAFConfig(USART1_PIN_IO, GetGPIOPin(USART1_PIN_TX), GPIO_AF_USART1);
            GPIO_PinAFConfig(USART1_PIN_IO, GetGPIOPin(USART1_PIN_RX), GPIO_AF_USART1);
            USART_OverSampling8Cmd(USART1, ENABLE); 
  
            ICB.GPIO_Pin = USART1_PIN_TX;
            GPIO_Init(USART1_PIN_IO, &ICB);
            GPIO_PinLockConfig(USART1_PIN_IO, ICB.GPIO_Pin);
            
            ICB.GPIO_Pin = USART1_PIN_RX;
            GPIO_Init(USART1_PIN_IO, &ICB);
            GPIO_PinLockConfig(USART1_PIN_IO, ICB.GPIO_Pin);
            break;
            
        case USART_NO2:
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);              /* Enable USART clock */
            GPIO_PinAFConfig(USART2_PIN_IO, GetGPIOPin(USART2_PIN_TX), GPIO_AF_USART2);
            GPIO_PinAFConfig(USART2_PIN_IO, GetGPIOPin(USART2_PIN_RX), GPIO_AF_USART2);
            USART_OverSampling8Cmd(USART2, ENABLE); 
            
            ICB.GPIO_Pin = USART2_PIN_TX;
            GPIO_Init(USART2_PIN_IO, &ICB);
            GPIO_PinLockConfig(USART2_PIN_IO, ICB.GPIO_Pin);
            
            ICB.GPIO_Pin = USART2_PIN_RX;
            GPIO_Init(USART2_PIN_IO, &ICB);
            GPIO_PinLockConfig(USART2_PIN_IO, ICB.GPIO_Pin);
            break;
            
        case USART_NO3:
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);              /* Enable USART clock */
            GPIO_PinAFConfig(USART3_PIN_IO, GetGPIOPin(USART3_PIN_TX), GPIO_AF_USART3);
            GPIO_PinAFConfig(USART3_PIN_IO, GetGPIOPin(USART3_PIN_RX), GPIO_AF_USART3);
            USART_OverSampling8Cmd(USART3, ENABLE); 
            
            ICB.GPIO_Pin = USART3_PIN_TX;
            GPIO_Init(USART3_PIN_IO, &ICB);
            GPIO_PinLockConfig(USART3_PIN_IO, ICB.GPIO_Pin);
            
            ICB.GPIO_Pin = USART3_PIN_RX;
            GPIO_Init(USART3_PIN_IO, &ICB);
            GPIO_PinLockConfig(USART3_PIN_IO, ICB.GPIO_Pin);
            break;
            
        default:
            break;
    }
}

/**************************************************************************************************
**  函数名称:  Debug_PrintByte
**  功能描述:  打印输出单个字节
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void Debug_PrintByte(INT8U byte)
{
    switch (DEBUG_UART_COM)
    {
        case USART_NO1:
            USART_SendData(USART1, (INT16U)byte);
            while ((USART1->SR & USART_SR_TXE) == 0) {};
            break;
            
        case USART_NO2:
            USART_SendData(USART2, (INT16U)byte);
            while ((USART2->SR & USART_SR_TXE) == 0) {};
            break;
            
        case USART_NO3:
            USART_SendData(USART3, (INT16U)byte);
            while ((USART3->SR & USART_SR_TXE) == 0) {};
            break;
            
        default:
            break;
    }
}

/**************************************************************************************************
**  函数名称:  Debug_PrintCRLF
**  功能描述:  在打印信息后补加回车换行符
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void Debug_PrintCRLF(void)
{
    Debug_PrintByte('\r');
    Debug_PrintByte('\n');
}

/**************************************************************************************************
**  函数名称:  Debug_PrintHex
**  功能描述:  以16进制格式打印连续数据
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void Debug_PrintHex(INT8U *ptr, INT16U size)
{
    INT8U  ch;
    INT16U i;

    for (i = 0; i < size; i++) {
        ch = *ptr++;
        Debug_PrintByte(TOOL_HexToChar(ch >> 4));
        Debug_PrintByte(TOOL_HexToChar(ch));
        Debug_PrintByte(' ');
    }
    
    Debug_PrintCRLF();                              /* 在结尾处补加一个回车换行符 */
}

/**************************************************************************************************
**  函数名称:  Debug_PrintStr
**  功能描述:  以字符串形式打印连续内容
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void Debug_PrintStr(char *ptr)
{
    INT32U i, tlen;

    tlen = strlen(ptr);

    for (i = 0; i < tlen; i++) {
        Debug_PrintByte(*ptr++);
    }
}

/**************************************************************************************************
**  函数名称:  Debug_Initiate
**  功能描述:  初始化打印串口
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void Debug_Initiate(void)
{
    USART_InitTypeDef       ICB;
    USART_ClockInitTypeDef  ICL;

    UART_IOCONFIG(DEBUG_UART_COM);

    ICB.USART_BaudRate            = DEBUG_BAUDRATE;
    ICB.USART_WordLength          = USART_WordLength_8b;
    ICB.USART_StopBits            = USART_StopBits_1;
    ICB.USART_Parity              = USART_Parity_No;
    ICB.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    ICB.USART_Mode                = USART_Mode_Tx;

    ICL.USART_Clock               = USART_Clock_Disable;
    ICL.USART_CPOL                = USART_CPOL_Low;
    ICL.USART_CPHA                = USART_CPHA_2Edge;
    ICL.USART_LastBit             = USART_LastBit_Disable;

    switch (DEBUG_UART_COM)                                             /* 不开启中断，仅使能串口功能 */
    {
        case USART_NO1:
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
            USART_Init(USART1, &ICB);
            USART_ClockInit(USART1, &ICL);
            USART_Cmd(USART1, ENABLE);
            break;
            
        case USART_NO2:
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
            USART_Init(USART2, &ICB);
            USART_ClockInit(USART2, &ICL);
            USART_Cmd(USART2, ENABLE);
            break;
            
        case USART_NO3:
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
            USART_Init(USART3, &ICB);
            USART_ClockInit(USART3, &ICL);
            USART_Cmd(USART3, ENABLE);
            break;
            
        default:
            break;
    }
}

#endif



